import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Genome {
    private final String name;
    private final List<Integer> blocks;

    public Genome(String name, List<Integer> blocks) {
        this.name = name;
        this.blocks = blocks;
    }

    public int blockCount() {
        return blocks.size();
    }

    public int getBlock(int idx) {
        return blocks.get(idx);
    }


    public String getName() {
        return name;
    }

    public void reverse(int from, int to) throws ParametersException {
        if (from >= to) {
            throw new ParametersException("Start should be less than finish");
        }
        if (from < 0 || to > blocks.size()) {
            throw new ParametersException("Start and finish should be greater or equal than zero and less or equal than number of blocks");
        }
        for (int i = from; i < to; i++) {
            int j = to - (i - from) - 1;
            if (j <= i) {
                break;
            }
            Collections.swap(blocks, i, j);
        }
        for (int i = from; i < to; i++) {
            blocks.set(i, -blocks.get(i));
        }
    }

    public void transposition(int from, int to, int position, boolean inv) throws ParametersException  {
        if (from >= to) {
            throw new ParametersException("Start should be less than finish");
        }
        if (position >= from && position < to) {
            throw new ParametersException("Insert position should not be between start and finish");
        }
        if (from < 0 || to > blocks.size()) {
            throw new ParametersException("Start and finish should be greater or equal than zero and less or equal than number of blocks");
        }
        if (position < 0 || position > blocks.size()) {
            throw new ParametersException("Insert position should be greater or equal than zero and less or equal than number of blocks");
        }

        if (position < from) {
            if (!inv) {
                reverse(position, to);
                reverse(position, position + to - from);
                reverse(position + to - from, to);
            } else {
                reverse(position + to - from, to);
                reverse(position, position + to - from);
                reverse(position, to);
            }
        } else {
            if (!inv) {
                reverse(from, position);
                reverse(from, position - (to - from));
                reverse(position - (to - from), position);
            } else {
                reverse(position - (to - from), position);
                reverse(from, position - (to - from));
                reverse(from, position);
            }
        }
    }

    public void insert(int position, List<Integer> blocks) throws ParametersException  {
        if (position < 0 || position > this.blocks.size()) {
            throw new ParametersException("Insert position should be greater or equal than zero and less or equal than number of blocks");
        }
        this.blocks.addAll(position, blocks);
    }

    public List<Integer> delete(int from, int to) throws ParametersException  {
        if (from >= to) {
            throw new ParametersException("Start should be less than finish");
        }
        if (from < 0 || to > blocks.size()) {
            throw new ParametersException("Start and finish should be greater or equal than zero and less or equal than number of blocks");
        }
        List<Integer> deleted = new ArrayList<>();
        for(int i=from;i<to;i++) {
            deleted.add(blocks.get(i));
        }
        blocks.subList(from, to).clear();
        return deleted;
    }
}
